﻿using System;
using System.Linq;
using Raven.Client;
using Raven.Client.Document;
using Raven.Client.Extensions;

namespace MyCRM.Infrastructure.Storage
{
    public class RavenDbUnitOfWork : IEventStoreUnitOfWork, IReadModelUnitOfWork
	{
		private readonly IDocumentStore _ravenClient;
		private readonly IDocumentSession _ravenSession;

		public RavenDbUnitOfWork(Uri storeUrl, string databaseName)
		{
			_ravenClient = new DocumentStore() { Url = storeUrl.ToString() }.Initialize();
			_ravenSession = GetDefaultOrSpecificDatabase(_ravenClient, databaseName);
		}

		private static IDocumentSession GetDefaultOrSpecificDatabase(IDocumentStore ravenClient, string databaseName)
		{
			if (String.IsNullOrEmpty(databaseName))
			{
				return ravenClient.OpenSession();
			}
			else
			{
				ravenClient.DatabaseCommands.EnsureDatabaseExists(databaseName);
				return ravenClient.OpenSession(databaseName);
			}
		}

		public IQueryable<T> Query<T>() where T:class, new()
		{
			return _ravenSession.Query<T>().Customize(x => x.WaitForNonStaleResults());
		}

		public void Delete<T>(T entity) where T : class, IEntity, new()
		{
			_ravenSession.Delete(entity);
		}

		public void Delete(object entity)
		{
			_ravenSession.Delete(entity);
		}

		public void Store<T>(T entity) where T : class,IEntity, new()
		{
			Store((object)entity);
		}

		public void Store(object entity)
		{
			_ravenSession.Store(entity);
		}

		public void SaveChanges()
		{
			_ravenSession.SaveChanges();
		}

		public void Dispose()
		{
			_ravenSession.Dispose();
			_ravenClient.Dispose();
		}
	}
}